import cv2 as cv
import numpy as np

# 图像的几何变换
# OpenCV提供了两个转换函数cv.warpAffine和cv.warpPerspective，你可以使用它们进行各种转换。
# cv.warpAffine采用2x3变换矩阵作为参数输入，而cv.warpPerspective采用3x3变换矩阵作为参数输入。


# cv2.getAffineTransform(mat_src, mat_dst) 得到变幻矩阵


img = cv.imread("img/cat.jpg", 0)

# 缩放
# 可以使用不同的插值方法，常用的插值方法是用于缩小的cv.INTER_AREA和用于缩放的cv.INTER_CUBIC（慢）和cv.INTER_LINEAR。
# 默认情况下，使用的插值方法是cv.INTER_LINEAR，它用于所有调整大小的操作
img = cv.resize(img, (300, 300), interpolation=cv.INTER_CUBIC)

# 平移
print(img.shape)
rows, cols = img.shape
# 变幻矩阵
M = np.float32([[1, 0, 100], [0, 1, 50]])
dis = cv.warpAffine(img, M, (cols, rows))

# 旋转
# 将图像相对于中心旋转90度而不进行任何缩放
# 主要用于获得图像绕着 某一点的旋转矩阵：
#   Mat getRotationMatrix2D(Point2f center, double angle, double scale)
#   参数详解：
#   Point2f center：表示旋转的中心点
#   double angle：表示旋转的角度
#   double scale：图像缩放因子
M = cv.getRotationMatrix2D((cols / 2, rows / 2), 90, 1)
dis = cv.warpAffine(img, M, (cols, rows))

# 仿射变换
# 在仿射变换中，原始图像中的所有平行线在输出图像中依旧平行。
# 为了找到变换矩阵，我们需要从输入图像中得到三个点，以及它们在输出图像中的对应位置。
# 然后cv.getAffineTransform将创建一个2x3矩阵，最后该矩阵将传递给cv.warpAffine。
post1 = np.float32([[50, 50], [50, 200], [200, 50]])
post2 = np.float32([[10, 100], [50, 200], [100, 250]])
M = cv.getAffineTransform(post1, post2)
dis = cv.warpAffine(img, M, (cols, rows))

# 透视变换
# 对于透视变换，需要一个3x3变换矩阵。
# 即使在转换之后，直线仍是直线。
# 要找到此变换矩阵，需要在输入图像上找4个点，以及它们在输出图像中的对应位置。
# 在这4个点中，其中任意3个不共线。
# 然后可以通过函数cv.getPerspectiveTransform找到变换矩阵，将cv.warpPerspective应用于此3x3变换矩阵。
post1 = np.float32([[50, 50], [250, 50], [250, 250], [50, 250]])
post2 = np.float32([[0, 0], [300, 0], [300, 300], [0, 300]])
M = cv.getPerspectiveTransform(post1, post2)
dis = cv.warpPerspective(img, M, (300, 300))

cv.imshow("img", dis)
cv.waitKey(0)
cv.destroyAllWindows()
